home *** CD-ROM | disk | FTP | other *** search
/ Die Speccy' 97 / Die Speccy' 97.iso / amiga_system / the_aminet / comm / bbs / s342q07.lha / floors.c < prev    next >
C/C++ Source or Header  |  1995-01-14  |  20KB  |  950 lines

  1. /*
  2. *       Floors.c
  3. *
  4. * Floor handling code for Citadel-86.
  5. */
  6. #include "ctdl.h"
  7. /*
  8. *       Contents
  9. */
  10. char SelDirs = FALSE,
  11. SelShared = FALSE,
  12. SelPriv = FALSE,
  13. SelRO = FALSE,
  14. SelNew = FALSE,
  15. SelAnon = FALSE;
  16. char ShowNew;
  17. char NotForgotten = TRUE;
  18. char JustChecking;
  19. char HasSkipped;
  20. static char maim;
  21. char FoundNew;
  22. static int  GlobalFloor;
  23. static int  MoveCount;
  24. extern struct floor  *FloorTab;
  25. extern rTable    *roomTab;
  26. extern CONFIG    cfg;
  27. extern aRoom     roomBuf;
  28. extern logBuffer logBuf;
  29. extern MessageBuffer   msgBuf;
  30. extern char      remoteSysop;
  31. extern int       thisRoom;
  32. extern char      loggedIn;       /* Are we logged in?            */
  33. extern int       TopFloor;
  34. extern char      *confirm;
  35. extern char      outFlag;
  36. extern char      onConsole;
  37. extern char      *baseRoom;
  38. static int FlagCheck(int i);
  39. int FindFloor(label name, char doPartial);
  40. /*
  41. * FloorRunner()
  42. *
  43. * This function runs through all the rooms on a floor, applying the given
  44. * function to all rooms on that floor.
  45. */
  46. int FloorRunner(int start, int (*func)(int r))
  47.   {
  48.   int rover, CurrentFloor;
  49.   if (start == ERROR) return ERROR;
  50.   CurrentFloor = roomTab[start].rtFlIndex;
  51.   if (!FloorTab[CurrentFloor].FlInuse)
  52.   CurrentFloor = 0;
  53.   /* start with current room, go through table */
  54.   for (rover = 0; rover < MAXROOMS; rover++)
  55.     {
  56.     /* deep breath ... should rewrite this, prime example of
  57.     programming via accretion. */
  58.     if (!FloorTab[roomTab[rover].rtFlIndex].FlInuse)
  59.     roomTab[rover].rtFlIndex = 0;
  60.     if ( roomTab[rover].rtFlIndex == CurrentFloor && (KnownRoom(rover) ||
  61.     (NotForgotten && roomTab[rover].rtflags.INUSE &&
  62.     (aide && (cfg.BoolFlags.aideSeeAll || onConsole) &&
  63.     (!roomTab[rover].rtflags.INVITE || SomeSysop())))))
  64.       {
  65.       if ((*func)(rover)) return rover;
  66.  
  67.       }
  68.  
  69.     }
  70.   return ERROR;
  71.  
  72.   }
  73. /*
  74. * NewRoom()
  75. *
  76. * This function gets next new room in system (like GotoRoom()) on the current
  77. * floor.
  78. */
  79. int NewRoom()
  80.   {
  81.   int CurrentFloor, OldFloor, roomNo;
  82.   OldFloor = thisFloor;
  83.   CurrentFloor = -1;
  84.   while (   (roomNo = FloorRunner(thisRoom, NSRoomHasNew)) == ERROR &&
  85.   CurrentFloor != TopFloor     )
  86.     {
  87.     thisRoom = FirstRoom(++CurrentFloor);
  88.  
  89.     }
  90.   if (CurrentFloor == TopFloor)
  91.   roomNo = 0;           /* no new-message rooms found */
  92.   getRoom(roomNo);
  93.   mPrintf("%s\n ", roomBuf.rbname);
  94.   /* really ugly kludge.  someday locate this gunk in gotoRoom() */
  95.   if (!KnownRoom(thisRoom))
  96.     {
  97.     SetKnown(0, MAXVISIT - 1, thisRoom, &logBuf);
  98.  
  99.     }
  100.   return !(OldFloor == roomTab[thisRoom].rtFlIndex);
  101.  
  102.   }
  103. /*
  104. * FirstRoom()
  105. *
  106. * This function gets the first room on the specified floor.
  107. */
  108. int FirstRoom(int FloorNo)
  109.   {
  110.   int rover;
  111.   for (rover = 0; rover < MAXROOMS; rover++)
  112.     {
  113.     if (     roomTab[rover].rtflags.INUSE &&
  114.     roomTab[rover].rtFlIndex == FloorNo    )
  115.     return rover;
  116.  
  117.     }
  118.   return ERROR;
  119.  
  120.   }
  121. /*
  122. * DoFloor()
  123. *
  124. * This function handles the fanout for floor commands.
  125. */
  126. int DoFloors()
  127.   {
  128.   int  toReturn;
  129.   char again, c[2];
  130.   char *FloorOpts[] =
  131.     {
  132.     TERM "Aide", TERM "Z\bForget", TERM "Skip",
  133.     TERM "Goto", TERM "Known Floors", TERM "C\b", ""
  134.  
  135.     };
  136.   SListBase  FSelects =
  137.     {
  138.     NULL, FindSelect, NULL, NoFree, NULL
  139.  
  140.     };
  141.   do
  142.     {
  143.     toReturn = GOOD_SELECT;
  144.     if (CmdMenuList(FloorOpts, &FSelects, "floor.mnu", c, TRUE, FALSE)
  145.     == BACKED_OUT) return GOOD_SELECT;
  146.     again = FALSE;
  147.     switch (c[0])
  148.       {
  149.       case 'A': toReturn = FAide();     break;
  150.       case 'Z': toReturn = FForget();     break;
  151.       case 'S':
  152.       case 'G': toReturn = FGotoSkip(c[0]);   break;
  153.       case 'K': toReturn = FKnown(ONLY_FLOORS);   break;
  154.       case 'C': toReturn = FConfigure();      break;
  155.       default:
  156.       ;
  157.  
  158.       }
  159.     if (toReturn == BACKED_OUT)
  160.       {
  161.       again = TRUE;
  162.       PushBack('\b');
  163.  
  164.       }
  165.  
  166.     }
  167.   while (again);
  168.   return toReturn;
  169.  
  170.   }
  171. /*
  172. * FInvite()
  173. *
  174. * This function is used to invite a user to all rooms on a floor.
  175. */
  176. void FInvite()
  177.   {
  178.   mPrintf("[%s]\n ", FloorTab[thisFloor].FlName);
  179.   getList(UserToFloor, "Invited users", NAMESIZE, FALSE);
  180.  
  181.   }
  182. static char YesInvite = TRUE;
  183. /*
  184. * FWithdraw()
  185. *
  186. * This function will withdraw invitations from a floor.
  187. */
  188. void FWithdraw()
  189.   {
  190.   mPrintf("[%s]\n ", FloorTab[thisFloor].FlName);
  191.   YesInvite = FALSE;
  192.   getList(UserToFloor, "Kicked out users", NAMESIZE, FALSE);
  193.   YesInvite = TRUE;
  194.  
  195.   }
  196. extern logBuffer logTmp;
  197. /*
  198. * UserToFloor()
  199. *
  200. * This function will invite the named user to current floor.  This function
  201. * is used in conjunction with getList().
  202. */
  203. int UserToFloor(char *name)
  204.   {
  205.   int logNo;
  206.   int InviteUserToFloor(int r);
  207.   logNo = findPerson(name, &logTmp);
  208.   if (logNo == ERROR)
  209.     Output_Citadel_Message("NODRFD", (long)name,NULL,NULL);
  210.   else
  211.     {
  212.     FloorRunner(thisRoom, InviteUserToFloor);
  213.     putLog(&logTmp, logNo);
  214.  
  215.     }
  216.   return TRUE;
  217.  
  218.   }
  219. /*
  220. * InviteUserToFloor()
  221. *
  222. * This function does the actual work of inviting a user.
  223. */
  224. int InviteUserToFloor(int r)
  225.   {
  226.   if (r != AIDEROOM)
  227.     {
  228.     if (YesInvite)
  229.     logTmp.lbgen[r] = (roomTab[r].rtgen << GENSHIFT) + MAXVISIT - 1;
  230.     else
  231.     logTmp.lbgen[r] = ((roomTab[r].rtgen + (MAXGEN-1)) % MAXGEN);
  232.  
  233.     }
  234.   return FALSE;
  235.  
  236.   }
  237. /*
  238. * FSkipped()
  239. *
  240. * This function will show skipped rooms and floors.
  241. */
  242. void FSkipped()
  243.   {
  244.   int rover, roomNo;
  245.   JustChecking = FALSE;
  246.   ShowNew = TRUE;
  247.   Output_Citadel_Message("SKPRMF",(long) FloorTab[thisFloor].FlName , NULL, NULL);
  248.   FloorRunner(thisRoom, SkippedNewRoom);
  249.   ShowNew = FALSE;
  250.   JustChecking = TRUE;
  251.   Output_Citadel_Message("SKPFLR", NULL, NULL, NULL);
  252.   for (rover = 1; rover < TopFloor; rover++)
  253.     {
  254.     roomNo = FirstRoom(rover);
  255.     if (FloorRunner(roomNo, SkippedNewRoom) != ERROR)
  256.       Output_Citadel_Message("FLRNNL",(long)FloorTab[rover].FlName , NULL, NULL);
  257.  
  258.     }
  259.   JustChecking = FALSE;
  260.   tableRunner(SkippedNewRoom, TRUE);
  261.  
  262.   }
  263. /*
  264. * FForget()
  265. *
  266. * This function will forget a floor.
  267. */
  268. char FForget()
  269.   {
  270.   Output_Citadel_Message("FLOORN",(long)FloorTab[roomTab[thisRoom].rtFlIndex].FlName, NULL, NULL);
  271.   if (!getYesNo("CONFRM")) return GOOD_SELECT;
  272.   FloorRunner(thisRoom, Zroom);
  273.   gotoRoom(baseRoom, 'S');
  274.   return GOOD_SELECT;
  275.  
  276.   }
  277. /*
  278. * FConfigure()
  279. *
  280. * This function will change floor configuration value.
  281. */
  282. char FConfigure()
  283.   {
  284.   FloorMode = !FloorMode;
  285.   mPrintf("%s mode\n ", (FloorMode) ? "FLOOR" : "Normal");
  286.   return GOOD_SELECT;
  287.  
  288.   }
  289. /*
  290. * FGotoSkip()
  291. *
  292. * This function will let us Skip an entire floor.
  293. */
  294. char FGotoSkip(int mode)
  295.   {
  296.   label floorName;
  297.   int   floorNo, newRoom, rover;
  298.   char  dispbuf[40];
  299.   outFlag = IMPERVIOUS;
  300.   if (mode == 'S')
  301.     {
  302.     sPrintf(dispbuf, "[%s] goto ",
  303.     FloorTab[roomTab[thisRoom].rtFlIndex].FlName);
  304.     mPrintf("%s", dispbuf);
  305.  
  306.     }
  307.   if (getNormStr("", floorName, NAMESIZE, BS_VALID) == BACKED_OUT)
  308.     {
  309.     if (mode == 'S')
  310.     for (rover = 0; rover < strLen(dispbuf); rover++)
  311.     mPrintf("\b \b");
  312.     return BACKED_OUT;
  313.  
  314.     }
  315.   if (strLen(floorName) != 0)
  316.     {
  317.     if ((floorNo = FindFloor(floorName, TRUE)) == ERROR)
  318.       {
  319.       Output_Citadel_Message("NODRFD", (long)floorName,NULL, NULL);
  320.       return GOOD_SELECT;
  321.  
  322.       }
  323.     if ((newRoom = FloorRunner(FirstRoom(floorNo), FindAny)) == ERROR)
  324.       {
  325.       Output_Citadel_Message("NOKNRM",(long) FloorTab[floorNo].FlName, NULL, NULL );
  326.       return GOOD_SELECT;
  327.  
  328.       }
  329.  
  330.     }
  331.   else
  332.     {
  333.     floorNo = thisFloor;
  334.     for (rover = 0; rover < TopFloor; rover++)
  335.     if (rover != floorNo && FloorTab[rover].FlInuse)
  336.       {
  337.       newRoom = FirstRoom(rover);
  338.       if ((newRoom = FloorRunner(newRoom, NSRoomHasNew)) != ERROR)
  339.       break;
  340.  
  341.       }
  342.     if (rover == TopFloor)
  343.     newRoom = 0;
  344.  
  345.     }
  346.   if (mode == 'S') FloorRunner(thisRoom, FSroom);
  347.   gotoRoom(roomTab[newRoom].rtname, mode);
  348.   return GOOD_SELECT;
  349.  
  350.   }
  351. /*
  352. * FindFloor()
  353. *
  354. * This function returns index for the given floor name.
  355. */
  356. int FindFloor(label name, char doPartial)
  357.   {
  358.   int rover;
  359.   for (rover = 0; rover < TopFloor; rover++)
  360.     {
  361.     if (strCmpU(name, FloorTab[rover].FlName) == SAMESTRING &&
  362.     FloorTab[rover].FlInuse)
  363.       {
  364.       return rover;
  365.  
  366.       }
  367.  
  368.     }
  369.   if (doPartial)
  370.   for (rover = 0; rover < TopFloor; rover++)
  371.     {
  372.     if (FloorTab[rover].FlInuse &&
  373.     matchString(FloorTab[rover].FlName, name,
  374.     lbyte(FloorTab[rover].FlName)) != NULL)
  375.     return rover;
  376.  
  377.     }
  378.   return ERROR;
  379.  
  380.   }
  381. /*
  382. * FAide()
  383. *
  384. * This function handles the floor-oriented aide commands.
  385. */
  386. char FAide()
  387.   {
  388.   char *FloorAideOpts[] =
  389.     {
  390.     "Create Floor\n", "Delete empty floors\n", "Move rooms\n",
  391.     "Kill Floor\n", "Rename Floor\n", "Floor moderator\n",
  392.     "Invite users to floor", "Withdraw users from floor", "\b", ""
  393.  
  394.     };
  395.   if (!aide)
  396.     {
  397.     if (loggedIn && strCmpU(logBuf.lbname, FloorTab[thisFloor].FlModerator) ==
  398.     SAMESTRING)
  399.       {
  400.       RenameFloor();
  401.       return GOOD_SELECT;
  402.  
  403.       }
  404.     else
  405.     return BAD_SELECT;    /* Indicates problem */
  406.  
  407.     }
  408.   RegisterThisMenu("aideflr.mnu", FloorAideOpts);
  409.   switch (GetMenuChar())
  410.     {
  411.     case 'C': CreateFloor();      break;
  412.     case 'D': DeleteFloors();     break;
  413.     case 'M': MoveRooms();        break;
  414.     case 'K': KillFloor();        break;
  415.     case 'R': RenameFloor();      break;
  416.     case 'F': FlModerator();      break;
  417.     case 'I': FInvite();        break;
  418.     case 'W': FWithdraw();        break;
  419.     case '\b': return BACKED_OUT;
  420.  
  421.     }
  422.   return GOOD_SELECT;
  423.  
  424.   }
  425. /*
  426. * FlModerator()
  427. *
  428. * This function handles the floor moderator.
  429. */
  430. void FlModerator()
  431.   {
  432.   label buffer;
  433.   if (WhoIsModerator(buffer))
  434.     {
  435.     strCpy(FloorTab[thisFloor].FlModerator, buffer);
  436.     putFloor(thisFloor);
  437.     ZeroMsgBuffer(&msgBuf);
  438.     sPrintf(msgBuf.mbtext, "%s's moderator set to %s by %s.",
  439.     FloorTab[thisFloor].FlName, buffer, logBuf.lbname);
  440.     aideMessage(NULL,FALSE);
  441.  
  442.     }
  443.  
  444.   }
  445. /*
  446. * DeleteFloors()
  447. *
  448. * This function deletes empty floors.
  449. */
  450. void DeleteFloors()
  451.   {
  452.   int rover, count = 0;
  453.   ZeroMsgBuffer(&msgBuf);
  454.   sPrintf(msgBuf.mbtext, "Following empty floors deleted by %s: ",
  455.   logBuf.lbname);
  456.   for (rover = 1; rover < TopFloor; rover++)
  457.     {
  458.     if (FloorTab[rover].FlInuse)
  459.       {
  460.       if (FirstRoom(rover) == ERROR)
  461.         {
  462.         count++;
  463.         FloorTab[rover].FlInuse = FALSE;
  464.         putFloor(rover);
  465.         sPrintf(lbyte(msgBuf.mbtext), "[%s], ", FloorTab[rover].FlName);
  466.  
  467.         }
  468.  
  469.       }
  470.  
  471.     }
  472.   if (count)
  473.     {
  474.     *(lbyte(msgBuf.mbtext) - 2) = '.';
  475.     *(lbyte(msgBuf.mbtext) - 1) = 0;
  476.  
  477.     }
  478.   aideMessage(NULL,FALSE);
  479.  
  480.   }
  481. /*
  482. * MoveRooms()
  483. *
  484. * This function moves a series of rooms into the current floor.
  485. */
  486. void MoveRooms()
  487.   {
  488.   int   CurrentRoom;
  489.   char  *end;
  490.   CurrentRoom = thisRoom;
  491.   GlobalFloor = thisFloor;
  492.   MoveCount = 0;
  493.   ZeroMsgBuffer(&msgBuf);
  494.   sPrintf(msgBuf.mbtext, "Following rooms moved to floor %s by %s: ",
  495.   FloorTab[thisFloor].FlName, logBuf.lbname);
  496.   getList(MoveToFloor, "Rooms to move to this floor", NAMESIZE, FALSE);
  497.   getRoom(CurrentRoom);       /* MoveToFloor changes thisRoom & roomBuf */
  498.   if (MoveCount != 0)
  499.     {
  500.     end = lbyte(msgBuf.mbtext);
  501.     *(end - 2) = '.';
  502.     *(end - 1) = 0;
  503.     aideMessage(NULL,FALSE);
  504.  
  505.     }
  506.  
  507.   }
  508. /*
  509. * MoveToFloor()
  510. *
  511. * This function will move a single room to a floor.
  512. */
  513. int MoveToFloor(char *name)
  514.   {
  515.   int roomNo;
  516.   if ((roomNo = roomExists(name)) == ERROR)
  517.     {
  518.     Output_Citadel_Message("NOROOM",(long)name,NULL,NULL);
  519.     return TRUE;
  520.  
  521.     }
  522.   if (   roomNo == LOBBY  ||  roomNo == MAILROOM  ||  roomNo == AIDEROOM  )
  523.     {
  524.     if (!getYesNo("WRMVSP")) return TRUE;
  525.  
  526.     }
  527.   MoveCount++;
  528.   getRoom(roomNo);
  529.   roomBuf.rbFlIndex = GlobalFloor;
  530.   putRoom(roomNo);
  531.   noteRoom();
  532.   sPrintf(lbyte(msgBuf.mbtext), "%s, ", formRoom(thisRoom, FALSE, FALSE));
  533.   return TRUE;
  534.  
  535.   }
  536. /*
  537. * RenameFloor()
  538. *
  539. * This function renames a floor.
  540. */
  541. void RenameFloor()
  542.   {
  543.   label FloorName;
  544.   int   ReturnNo;
  545.   if (thisFloor == 0)
  546.     {
  547.     Output_Citadel_Message("USECFG",NULL ,NULL,NULL);
  548.     return ;
  549.  
  550.     }
  551.   if (!getXString("FLRNIT", FloorName, NAMESIZE, NULL, NULL))
  552.   return ;
  553.   if ((ReturnNo = FindFloor(FloorName, FALSE)) != ERROR)
  554.     {
  555.     if (ReturnNo != thisFloor)
  556.       {
  557.       Output_Citadel_Message("ALRYFR",(long)FloorName,NULL,NULL);
  558.       return;
  559.  
  560.       }
  561.  
  562.     }
  563.   ZeroMsgBuffer(&msgBuf);
  564.   sPrintf(msgBuf.mbtext, "The floor %s renamed to %s by %s.",
  565.   FloorTab[thisFloor].FlName, FloorName, logBuf.lbname);
  566.   strCpy(FloorTab[thisFloor].FlName, FloorName);
  567.   putFloor(thisFloor);
  568.   aideMessage(NULL,FALSE);
  569.  
  570.   }
  571. /*
  572. * CreateFloor()
  573. *
  574. * This function creates a floor.
  575. */
  576. void CreateFloor()
  577.   {
  578.   label FloorName;
  579.   int   rover;
  580.   if (  thisRoom == LOBBY ||
  581.   thisRoom == MAILROOM ||
  582.   thisRoom == AIDEROOM  )
  583.     {
  584.     Output_Citadel_Message("CCRFLR",NULL, NULL, NULL);
  585.     return ;
  586.  
  587.     }
  588.   if (!getXString("FLRNIT", FloorName, NAMESIZE, NULL, NULL))
  589.   return ;
  590.   if (FindFloor(FloorName, FALSE) != ERROR)
  591.     {
  592.     Output_Citadel_Message("ALRYFR",(long)FloorName,NULL,NULL);
  593.     return;
  594.  
  595.     }
  596.   for (rover = 1; rover < TopFloor; rover++)
  597.   if (!FloorTab[rover].FlInuse) break;
  598.   if (rover == TopFloor)
  599.     {
  600.     FloorTab = (struct floor *) realloc(FloorTab,
  601.     sizeof *FloorTab * ++TopFloor);
  602.  
  603.     }
  604.   roomBuf.rbFlIndex = rover;
  605.   FloorTab[rover].FlInuse = TRUE;
  606.   strCpy(FloorTab[rover].FlName, FloorName);
  607.   putFloor(rover);
  608.   putRoom(thisRoom);
  609.   noteRoom();
  610.   ZeroMsgBuffer(&msgBuf);
  611.   sPrintf(msgBuf.mbtext, "The floor %s created by %s.", FloorName,
  612.   logBuf.lbname);
  613.   aideMessage(NULL,FALSE);
  614.  
  615.   }
  616. /*
  617. * putFloor()
  618. *
  619. * This will put a floor record out to disk.
  620. */
  621. void putFloor(int i)
  622.   {
  623.   SYS_FILE name;
  624.   FILE *fd;
  625.   long r;
  626.   extern char *R_W_ANY;
  627.   makeSysName(name, "ctdlflr.sys", &cfg.floorArea);
  628.   if ((fd = safeopen(name, R_W_ANY)) == NULL)
  629.   crashout("Couldn't open the floor file for update!");
  630.   r = i * sizeof *FloorTab;
  631.   fseek(fd, r, 0);
  632.   if (fwrite(FloorTab + i, sizeof *FloorTab, 1, fd) != 1)
  633.   crashout("?putFloor(): write failed!");
  634.   fclose(fd);
  635.  
  636.   }
  637. /*
  638. * KillFloor()
  639. *
  640. * This function kills a floor.
  641. */
  642. void KillFloor()
  643.   {
  644.   int CurrentFloor, CurrentRoom;
  645.   if (roomBuf.rbFlIndex == 0)
  646.     {
  647.     Output_Citadel_Message("NOKILF",NULL ,NULL,NULL);
  648.     return;
  649.  
  650.     }
  651.   if (!getYesNo("CONFRM")) return;
  652.   ZeroMsgBuffer(&msgBuf);
  653.   sPrintf(msgBuf.mbtext, "Floor %s killed by %s.",
  654.   FloorTab[thisFloor].FlName, logBuf.lbname);
  655.   aideMessage(NULL,FALSE);
  656.   CurrentFloor = thisFloor;   /* #define in CTDL.H */
  657.   CurrentRoom  = thisRoom;
  658.   maim = getYesNo("MVALLM");
  659.   FloorRunner(thisRoom, MaimOrKill);
  660.   FloorTab[CurrentFloor].FlInuse = FALSE;
  661.   putFloor(CurrentFloor);
  662.   /* due to behavior of MaimOrKill */
  663.   getRoom((!maim) ? LOBBY : CurrentRoom);
  664.  
  665.   }
  666. /*
  667. * MaimOrKill()
  668. *
  669. * This will kill or move a room to the main floor.
  670. */
  671. int MaimOrKill(int i)
  672.   {
  673.   getRoom(i);
  674.   if (maim)
  675.     {
  676.     roomBuf.rbFlIndex = 0;
  677.  
  678.     }
  679.   else
  680.     {
  681.     roomBuf.rbflags.INUSE = FALSE;
  682.  
  683.     }
  684.   putRoom(i);
  685.   noteRoom();
  686.   return FALSE;
  687.  
  688.   }
  689. /*
  690. * FKnown()
  691. *
  692. * This function will handle the ticklish task of floor display.
  693. */
  694. char FKnown(char mode)
  695.   {
  696.   int         rover, roomNo;
  697.   extern int  DirAlign;
  698.   extern char AlignChar;
  699.   switch (mode)
  700.     {
  701.     case FORGOTTEN:
  702.       Output_Citadel_Message("FORGFL",NULL,NULL,NULL);
  703.     ShowNew = 2;
  704.     SelNew = TRUE;
  705.     RunDisplay();
  706.     SelNew = FALSE;
  707.     break;
  708.     case INT_NOVICE:
  709.     case INT_EXPERT:
  710.     case NOT_INTRO:
  711.     if (SelNew)
  712.       Output_Citadel_Message("RMUNRF",(long)FloorTab[thisFloor].FlName,NULL,NULL);
  713.     ShowNew = TRUE;
  714.     FloorRunner(thisRoom, DispRoom);
  715.     if (mode == INT_NOVICE || mode == NOT_INTRO)
  716.       {
  717.       Output_Citadel_Message("NOUNSN",NULL,NULL,NULL);
  718.       ShowNew = FALSE;
  719.       FloorRunner(thisRoom, DispRoom);
  720.  
  721.       }
  722.     if (SelNew)
  723.       {
  724.       Output_Citadel_Message("OTFLUM",NULL,NULL,NULL);
  725.       for (rover = 0; rover < TopFloor; rover++)
  726.         {
  727.         if (rover != roomBuf.rbFlIndex)
  728.           {
  729.           roomNo = FirstRoom(rover);
  730.           if (FloorRunner(roomNo, RoomHasNew) != ERROR)
  731.             Output_Citadel_Message("FLRNNL", (long)FloorTab[rover].FlName,NULL,NULL);
  732.  
  733.           }
  734.  
  735.         }
  736.  
  737.       }
  738.     break;
  739.     case DR_SEL:
  740.     case SH_SEL:
  741.     case PR_SEL:
  742.     case ANON_SEL:
  743.     case READONLY:
  744.     RunDisplay();
  745.     break;
  746.     default:
  747.     SelNew = TRUE;
  748.     doCR();
  749.     Output_Citadel_Message("FLRWUR", NULL,NULL,NULL);
  750.     ShowNew = FoundNew = TRUE;
  751.     RunDisplay();
  752.     doCR();
  753.     Output_Citadel_Message("FLRWNR", NULL,NULL,NULL);
  754.     ShowNew = FoundNew = FALSE;
  755.     RunDisplay();
  756.     SelNew = FALSE;
  757.  
  758.     }
  759.   return GOOD_SELECT;
  760.  
  761.   }
  762. /*
  763. * RunDisplay()
  764. *
  765. * This will do the actual work of displaying in Floor mode.
  766. */
  767. void RunDisplay()
  768.   {
  769.   extern int  DirAlign;
  770.   extern char AlignChar;
  771.   int rover, roomNo;
  772.   AlignChar = ' ';
  773.   for (rover = 0; rover < TopFloor; rover++)
  774.     {
  775.     if (FloorTab[rover].FlInuse)
  776.       {
  777.       roomNo = FirstRoom(rover);
  778.       if (FloorRunner(roomNo, CheckFloor) != ERROR)
  779.         {
  780.         DispFloorName(rover);
  781.         FloorRunner(roomNo, DispRoom);
  782.         DirAlign = 0;
  783.  
  784.         }
  785.  
  786.       }
  787.  
  788.     }
  789.  
  790.   }
  791. /*
  792. * DispFloorName()
  793. *
  794. * This function displays a floor name with periods, etc...
  795. */
  796. void DispFloorName(int FloorNo)
  797.   {
  798.   int i;
  799.   extern int DirAlign;
  800.   extern char AlignChar;
  801.   Output_Citadel_Message("FLRSNL", (long)FloorTab[FloorNo].FlName,NULL,NULL);
  802.   if (termWidth >= 50)
  803.     {
  804.     DirAlign = 24;
  805.     AlignChar = ' ';
  806.     for (i = strLen(FloorTab[FloorNo].FlName); i < 21; i++)
  807.     mPrintf(".");
  808.  
  809.     }
  810.   else mPrintf("-");
  811.  
  812.   }
  813. /*
  814. * These functions are used as arguments to FloorRunner
  815. */
  816. /*
  817. * RoomHasNew()
  818. *
  819. * This returns TRUE if room has new messages for the current user.
  820. */
  821. int RoomHasNew(int i)
  822.   {
  823.   return (    roomTab[i].rtlastMessage >
  824.   logBuf.lbvisit[logBuf.lbgen[i] & CALLMASK] &&
  825.   roomTab[i].rtlastMessage >= cfg.oldest     );
  826.  
  827.   }
  828. /*
  829. * CheckFloor()
  830. *
  831. * This multipurpose function returns true of one of the combinations is
  832. * true.
  833. */
  834. int CheckFloor(int i)
  835.   {
  836.   #ifdef OLD_STYLE
  837.   if (( SelDirs   &&   roomTab[i].rtflags.ISDIR   ) ||
  838.   ( SelShared &&   roomTab[i].rtflags.SHARED  ) ||
  839.   ( SelPriv   &&   !roomTab[i].rtflags.PUBLIC ) ||
  840.   ( SelAnon   &&   roomTab[i].rtflags.ANON )    ||
  841.   ( SelRO     &&   roomTab[i].rtflags.READ_ONLY )    ||
  842.   ( SelNew && (ShowNew == 2 || (RoomHasNew(i) && FoundNew) ||
  843.   (!RoomHasNew(i) && !FoundNew))))
  844.   return TRUE;
  845.   #else
  846.   if (FlagCheck(i) ||
  847.   ( SelNew && (ShowNew == 2 || (RoomHasNew(i) && FoundNew) ||
  848.   (!RoomHasNew(i) && !FoundNew))))
  849.   return TRUE;
  850.   #endif
  851.   return FALSE;
  852.  
  853.   }
  854. /*
  855. * NSRoomHasNew()
  856. *
  857. * TRUE if room has new messages and isn't skipped.
  858. */
  859. int NSRoomHasNew(int i)
  860.   {
  861.   if (!roomTab[i].rtflags.SKIP && RoomHasNew(i))
  862.   return TRUE;
  863.   if (roomTab[i].rtflags.SKIP) /* Kludge this in -- ugly but useful */
  864.   HasSkipped = TRUE;
  865.   return FALSE;
  866.  
  867.   }
  868. /*
  869. * DispRoom()
  870. *
  871. * This function will display a room name.
  872. */
  873. int DispRoom(int i)
  874.   {
  875.   char HasNew;
  876.   extern char shownHidden;
  877.   HasNew = RoomHasNew(i);
  878.   if (FlagCheck(i) ||
  879.   ( SelNew &&
  880.   (ShowNew == 2 || (HasNew && ShowNew == 1) ||
  881.   (!HasNew && !ShowNew))))
  882.     {
  883.     Output_Citadel_Message("DISPRM",(long)formRoom(i, TRUE, TRUE),NULL,NULL);
  884.     if (!roomTab[i].rtflags.PUBLIC) shownHidden = TRUE;
  885.     if (SelDirs && HalfSysop())
  886.       {
  887.       if (FindDirName(i) != NULL)
  888.         Output_Citadel_Message("DISPDR",(long)FindDirName(i),NULL,NULL);
  889.       else
  890.         Output_Citadel_Message("DISPNF",NULL,NULL,NULL);
  891.  
  892.       }
  893.  
  894.     }
  895.   return FALSE;
  896.  
  897.   }
  898. /*
  899. * Zroom()
  900. *
  901. * This lets us Zforget a room.  Used for ;Z.
  902. */
  903. int Zroom(int i)
  904.   {
  905.   int r;
  906.   if (     i == LOBBY    ||
  907.   i == MAILROOM ||
  908.   i == AIDEROOM      )
  909.     {
  910.     return FALSE;
  911.  
  912.     }
  913.   r = (roomTab[i].rtgen + FORGET_OFFSET) % MAXGEN;
  914.   logBuf.lbgen[i] = r << GENSHIFT;
  915.   return FALSE;
  916.  
  917.   }
  918. /*
  919. * FSroom()
  920. *
  921. * This will skip a room on a floor.
  922. */
  923. int FSroom(int i)
  924.   {
  925.   roomTab[i].rtflags.SKIP = 1;     /* Set bit */
  926.   return FALSE;
  927.  
  928.   }
  929. /*
  930. * FindAny()
  931. *
  932. * This finds any known room on a floor.
  933. */
  934. int FindAny(int i)
  935.   {
  936.   return TRUE;        /* My, that was easy... */
  937.  
  938.   }
  939. static int FlagCheck(int i)
  940.   {
  941.   if (( SelDirs   &&   roomTab[i].rtflags.ISDIR   ) ||
  942.   ( SelShared &&   roomTab[i].rtflags.SHARED  ) ||
  943.   ( SelPriv   &&   !roomTab[i].rtflags.PUBLIC ) ||
  944.   ( SelAnon   &&   roomTab[i].rtflags.ANON )    ||
  945.   ( SelRO     &&   roomTab[i].rtflags.READ_ONLY ))
  946.   return TRUE;
  947.   return FALSE;
  948.  
  949.   }
  950.